package cn.bookcycle.requestroom.util;

import java.util.HashMap;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.bookcycle.requestroom.ConstantData.BusinessConstant;
import cn.bookcycle.requestroom.ConstantData.DBConstant;
import cn.bookcycle.requestroom.pojo.DateRecord;
import cn.bookcycle.requestroom.pojo.RoomForList;
import cn.bookcycle.requestroom.pojo.RoomInfo;
import cn.bookcycle.requestroom.pojo.UserInfo;

/**
 * 数据格式转换工具类
 *
 * @author liufenglin
 * @date 2018年3月4日
 */
public class DataFormatConvert {
	private static final Logger logger = LoggerFactory.getLogger(DataFormatConvert.class);
	/**
	 * 将key1=value1&key2=value2格式字符串转Map
	 * 
	 * @param paraStr
	 * @return
	 */
	public static Map paraToMap(String paraStr) {
		Map<String, Object> map = new HashMap<String, Object>();
		// 把所有参数组成的字符串切割成key=value形式的数组
		String para[] = paraStr.split(DBConstant.AND_SING);
		// 遍历所有的key=value
		for (int i = 0; i < para.length; ++i) {
			// 找到等号的位置
			int index = para[i].indexOf(DBConstant.EQUAL_SIGN);
			// 取出key
			String key = para[i].substring(0, index);
			logger.info("key={}", key);
			// 取出value
			String value = para[i].substring(index + 1);
			logger.info("value={}", value);
			// 如果是必须的参数，就放到map中
			if (BusinessConstant.NECESSARY_PARA_STR.contains(key)) {
				// 如果是data参数还要进行数据的格式转化
				if (DBConstant.DATE.equals(key)) {
					// 首先去掉时间格式中的-符号
					value = value.replace(DBConstant.LINE_SIGN, DBConstant.NULL_SIGN);
					// 然后去除时间格式中的T符号
					value = value.replace(DBConstant.T_SIGN, DBConstant.NULL_SIGN);
					// 最后去除时间格式中的冒号
					value = value.replace(DBConstant.COLON_SIGN, DBConstant.NULL_SIGN);
				} else {}
				// 在map中放入参数的key和value
				map.put(key, value);
			} else {}
			
		} // end for
		logger.info("参数转化后的map:{}", map);
		return map;
	}
	
	/**
	 * 把User的json格式信息转换成User对象
	 * 
	 * @param userId
	 * @param json
	 * @return
	 */
	public static UserInfo jsonToUser(String userId, String json) {
		logger.info("jsonToUser函数收到的请求json字符串是：{}", json);
		UserInfo user = new UserInfo();
		user.setUserId(userId);
		
		if (json == null) {
			// 该用户从未使用过免费看房次数
			user.setUsedFreeCount(0);
		} else {
			// 对获取到的用户信息进行转换
			try {
				// 这里得到的json信息，应该是只有一个jsonObject，所以只需要对取位置为0的Object
				JSONArray jsonArray = new JSONArray(json);
				JSONObject jsonObject = jsonArray.getJSONObject(0);
				int usedFreeChance = (int) jsonObject.get(DBConstant.FREE_COUNT);
				user.setUsedFreeCount(usedFreeChance);
				logger.info("查询到用户ID:{}, 用户已经使用的免费看房次数{}", userId, usedFreeChance);
			} catch (JSONException e) {
				logger.info("jsonToUser 解析JSON参数出现异常！！！");
			}
		} // end if if (json == null) ... else ...
		return user;
	}
	
	/**
	 * 由获取到的看房记录信息生成RoomInfo对象，并根据实际情况修改看房记录信息
	 * 
	 * @param roomId 
	 * @param jsonArrayStr
	 * @param dateRecord
	 * @return
	 */
	public static RoomInfo jsonToRoom(String roomId, String jsonArrayStr, DateRecord dateRecord) {
		logger.info("jsonToRoom is coming！！！！");
		
		RoomInfo room = new RoomInfo();
		room.setRoomId(roomId);
		JSONArray jsonArray = null;
		JSONObject jsonObject = new JSONObject();
		// 本次看房起始时间前一个时间
		String preNow = null;
		// preNow所在的索引
		int preNowIndex = 0;
		// 本次看房起始时间后一个时间
		String nextNow = null;
		// 本次看房起始时间前一个时间的持续时间
		String preNowDuration = null;
		// 本次看房起始时间前一个时间的结束时间
		String preNowEndDate = null;
		// 本次看房起始时间后一个时间的持续时间
		String nextNowDuration = null;
		// 本次看房起始时间的持续时间
		String nowEndDate = null;
		// 记录数据的数据项多少
		int size = 0;
		// 起始时间记录串
		String start = null;
		// 持续时间记录串
		String duration = null;
		
		logger.info("jsonArrayStr:{} roomId:{}", jsonArrayStr, roomId);
		
		/* 
		 * 根据数据库中是否存在看房记录，分两种情况处理看房请求
		 */
		if (jsonArrayStr == null) {
			// 说明数据库里没有该房间的看房记录信息,说明房间为空
			room.setEmpty(true);
			// 更新size、start、duration
			size = 1;
			start = dateRecord.getStartDate() + DBConstant.COMMA;
			duration = String.valueOf(dateRecord.getDuration()) + DBConstant.COMMA;
		} else {
			// 解析JSONArray格式的参数，并获取JOSNObject
			try {
				jsonArray = new JSONArray(jsonArrayStr);
				jsonObject = jsonArray.getJSONObject(0);
			} catch (JSONException e) {
				logger.info("jsonToRoom 解析JOSN 出现异常！！！");
			}
			// 从看房记录的JSONObjec获取size，start，duration信息
			try {
				size = jsonObject.getInt(DBConstant.SIZE);
				start = jsonObject.getString(DBConstant.START);
				duration = jsonObject.getString(DBConstant.DURATION);
			} catch (JSONException e) {
				logger.info("jsonToRoom 从JSONObject中获取数据异常！！！！");
			}
			/* 
			 * 通过二分查找，找到在record信息中，比本次看房起始时间前一个时间preNow,
			 * 和后一个时间nextNow以及preNow所在的索引位置
			 */
			// 把起始时间记录串切分为字符串组
			String startArray [] = start.split(DBConstant.COMMA);
			// 把持续时间记录串切分为字符串组
			String durationArray[] = duration.split(DBConstant.COMMA);
			// 通过二分查找，确定当前看房时间的前一个看房时间在数组中的索引
			preNowIndex = SearchUtil.binarySearchPreNowIndex(startArray, dateRecord.getStartDate());
			/* 
			 * 根据当前看房时间和，它前一个及后一个看房时间的关系，来确定房间是否为空，即是否可以看房
			 */
			if (preNowIndex == startArray.length - 1) {
				// 当前时间是晚于所有记录时间的情况，只存在preNow
				preNow = startArray[startArray.length - 1];
				preNowDuration = durationArray[startArray.length - 1];
				// 计算当前看房时间的前一个时间的结束时间
				preNowEndDate = TimeUtil.addMinutes(preNow, Integer.valueOf(preNowDuration));
				if (TimeUtil.compareDate(dateRecord.getStartDate(), preNowEndDate)) {
					// 记录中的最后一个时间点的结束时间早于当前看房起始时间，则可以看房
					room.setEmpty(true);
				} else {
					// 否则房间不为空，不能看房
					room.setEmpty(false);
				}
			} else if (preNowIndex == -1) {
				// 当前时间早于所有记录时间的情况，只存在nextNow
				nextNow = startArray[0];
				// 计算当前看房时间的结束时间
				nowEndDate = TimeUtil.addMinutes(dateRecord.getStartDate(), dateRecord.getDuration());
				if (TimeUtil.compareDate(nextNow, nowEndDate)) {
					// 当前看房时间的结束时间早于记录中的第一个时间点，则可以看房
					room.setEmpty(true);
				} else {
					// 否则房间不为空，不能看房
					room.setEmpty(false);
				}
			} else {
				// 当前时间在记录中存在前一个时间点和后一个时间点的情况
				preNow = startArray[preNowIndex];
				nextNow = startArray[preNowIndex + 1];
				// 根据索引查找preNow的持续时间
				preNowDuration = durationArray[preNowIndex];
				// 计算preNow的结束时间
				preNowEndDate = TimeUtil.addMinutes(preNow, Integer.valueOf(preNowDuration));
				nowEndDate = TimeUtil.addMinutes(dateRecord.getStartDate(), dateRecord.getDuration());
				if (TimeUtil.compareDate(dateRecord.getStartDate(), preNowEndDate) 
						&& TimeUtil.compareDate(nextNow, nowEndDate)) {
					// 如果当前看房时间的startDate晚于preNow的endDate，
					// 并且当前看房时间的endDate早于nextNow的startDate，就可以看房
					room.setEmpty(true);
				} else {}
			} // end if ... else if ... else ...
			
		} // end if (jsonArrayStr == null) ... else ...
		
		/*
		 * 如果房间为空，就将本次看房数据更新到start、duration记录中，并修改size，保存到数据库中
		 */
		if (room.isEmpty()) {
			logger.info("room is empty, 开始存储本次看房数据！！！");
			logger.info("jsonArrayStr == null: {}", jsonArrayStr == null);
			logger.info("jsonArrayStr:{}", jsonArrayStr);
			// 将本次看房记录的start和duration插入到JOSNObject中，形成新的看房记录数据（分两种情况）
			if (jsonArrayStr != null) {
				if (preNow == null) {
					// 将本次看房记录插入到start和duration串的最前端
					start = dateRecord.getStartDate() + DBConstant.COMMA + start;
					duration = dateRecord.getDuration() + DBConstant.COMMA + duration;
					// 更新size
					size = size + 1;
					logger.info("preNow == null 情况下，start:{}, duration:{}, size:{}", start, duration, size);
				} else {
					// 将本次看房记录分别插入到start和duration串的preNow和preNowIndex后面
					int location = start.indexOf(preNow);
					// 找到指定串的后面的逗号的位置
					int commaIndex = location + preNow.length();
					// 从逗号位置把字符串分为两部分
					String preStr = start.substring(0, commaIndex + 1);
					String nextStr = start.substring(commaIndex + 1);
					// 构造新的start
					start = preStr + dateRecord.getStartDate() + DBConstant.COMMA + nextStr;
					StringBuilder sb = new StringBuilder();
					for (int i = 0; i <= preNowIndex; ++i) {
						// 找到逗号所在的位置
						commaIndex = duration.indexOf(DBConstant.COMMA);
						// 把数据和逗号分隔符，一起放到StringBuilder中
						sb.append(duration.substring(0, commaIndex + 1));
						// 更新duration
						duration = duration.substring(commaIndex + 1);
					}
					// 在preNowIndex后面一个位置加上新的duration和逗号分隔符
					sb.append(dateRecord.getDuration() + DBConstant.COMMA);
					// 构造新的duration
					duration = sb.append(duration).toString();
					// 更新size
					size = size + 1;
					logger.info("preNow != null 情况下，start:{}, duration:{}, size:{}", start, duration, size);
				} // end if preNow == null ... else ...
			} else {} // if if (jsonArrayStr != null) ... else ...
			
			// 更新josnObject的内容，并存储到数据库
			try {
				jsonObject.put(DBConstant.ROOM_ID, roomId);
				jsonObject.put(DBConstant.SIZE, size);
				jsonObject.put(DBConstant.START, start);
				jsonObject.put(DBConstant.DURATION, duration);
			} catch (JSONException e) {
				logger.warn("jsonToRoom 更新jsonObject 异常！！！！！");
			}
			
			// 调用存储函数
//			if (jsonArrayStr == null) {
//				DaoUtil.updateCheckRoomRecord(jsonObject, DBConstant.INSERT);
//			} else {
				DaoUtil.updateCheckRoomRecord(jsonObject);
//			}
			
		} else {} // end if if (room.isEmpty()) ... else ..  房间不为空，本次申请看房失败
		
		return room;
	}
	
	/**
	 * 把JSONObject转为RoomForList对象
	 * 
	 * @param jsonObject
	 * @return
	 */
	public static RoomForList JS2RoomForList(JSONObject jsonObject) {
		RoomForList room = new RoomForList();
		String roomId = null;
		String date = null;
		String duration = null;
		boolean status = false;
		String openLockId = null;
		try {
			roomId = jsonObject.getString(DBConstant.ROOM_ID_T);
			// 对看房时间进行格式化年-月-日 时:分
			date = TimeUtil.formatDate(jsonObject.getString(DBConstant.date));
		    // 看房持续时间由分转为小时
			duration = TimeUtil.minute2Hour(jsonObject.getInt(DBConstant.DURATION));
			status = TimeUtil.judgeCheckAuthorizatiionStatus(jsonObject.getString(DBConstant.date), jsonObject.getInt(DBConstant.DURATION));
			openLockId = DaoUtil.getOpenLockIdByRoomId(roomId);
			logger.info("JS2RoomForList函数：roomId={}, date={}, duration={}, status={}", roomId, date, duration, status);
		} catch (JSONException e) {
			logger.warn("JS2RoomForList 取参数出现异常！！！！！");
		}
		room.setRoomId(roomId);
		room.setDate(date);
		room.setDuration(duration);
		room.setStatus(status);
		room.setOpenLockId(openLockId);
		return room;
	}
}
